package com.brutal.minigames.gop;

import java.awt.Polygon;

import com.rsbuddy.script.methods.Calculations;
import com.rsbuddy.script.methods.Camera;
import com.rsbuddy.script.methods.Mouse;
import com.rsbuddy.script.methods.Npcs;
import com.rsbuddy.script.methods.Objects;
import com.rsbuddy.script.methods.Players;
import com.rsbuddy.script.methods.Widgets;
import com.rsbuddy.script.util.Random;
import com.rsbuddy.script.wrappers.Area;
import com.rsbuddy.script.wrappers.Component;
import com.rsbuddy.script.wrappers.GameObject;
import com.rsbuddy.script.wrappers.Item;
import com.rsbuddy.script.wrappers.Npc;
import com.rsbuddy.script.wrappers.Player;
import com.rsbuddy.script.wrappers.Tile;

import org.rsbuddy.tabs.Equipment;
import org.rsbuddy.tabs.Inventory;
import org.rsbuddy.widgets.Bank;

public class Join extends Task {

	private final Team team;
	private final Area guild = new Area(1688, 5460, 1704, 5476);
	private final int[] yellowWizard = { 8030 };
	private final int[] greenWizard = { 8031 };
	private final int[] randomWizard = { 8033, 8034, 8035, 8036, 8037, 8038,
			8039 };
	private final boolean defend;
	private final int greenAttractor = 13645;
	private final int greenBarrierGenerator = 13647;
	private final int greenRepeller = 13646;
	private final int yellowAttractor = 13643;
	private final int yellowBarrierGenerator = 13648;
	private final int yellowRepeller = 13644;
	private String status = "Waiting";

	public Join(final Team team, final boolean defend) {
		this.team = team;
		this.defend = defend;
	}

	@Override
	public boolean isValid() {
		final Player player = Players.getLocal();
		if (player == null || player.getLocation() == null) {
			return false;
		}
		return guild.contains(player.getLocation());
	}

	@Override
	public void execute() {
		final int[] wizardId = (team == Team.GREEN ? greenWizard
				: (team == Team.YELLOW ? yellowWizard : randomWizard));
		final Npc wizard = Npcs.getNearest(wizardId);
		final Component acceptText = Widgets.getComponent(228, 2);
		final Component gearText = Widgets.getComponent(243, 4);
		final Component infoText = Widgets.getComponent(781, 56);
		final Component waitText = Widgets.getComponent(242, 5);
		final Component joinedText = Widgets.getComponent(242, 4);
		final Npc portal = Npcs.getNearest(8019);
		if (Players.getLocal().getAnimation() != -1) {
			return;
		}
		if (Camera.getPitch() < 90) {
			Camera.setPitch(100);
		}
		if (Inventory.getCount() > 20) {
			status = "Banking";
			depositAllExcept(greenAttractor, greenBarrierGenerator,
					greenRepeller, yellowAttractor, yellowBarrierGenerator,
					yellowRepeller);
			return;
		}
		if (!Inventory.containsOneOf(greenAttractor, greenBarrierGenerator,
				greenRepeller, yellowAttractor, yellowBarrierGenerator,
				yellowRepeller)
				&& !acceptText.isVisible()
				&& !gearText.isVisible()
				&& !infoText.isVisible() && !waitText.isVisible()) {
			if (wizard == null) {
				return;
			}
			if (!wizard.isOnScreen()) {
				status = "Turning to wizard";
				Camera.turnTo(wizard);
				sleep(900, 1100);
			}
			if (!wizard.isOnScreen()) {
				wizard.getLocation().randomize(3, 3).clickOnMap();
				sleep(1100, 1300);
			}
			status = "Joining " + team.toString();
			if (!interact(wizard, "Join")) {
				sleep(300, 500);
				wizard.interact("Join");
			}
			sleep(1100, 1300);
			if (joinedText.containsText("I've put you on")) {
				Widgets.clickContinue();
				sleep(300, 500);
			}
			return;
		}
		if (acceptText.isValid() && acceptText.isVisible()) {
			acceptText.click();
			sleep(1100, 1300);
			return;
		}
		if (gearText.isValid()
				&& gearText.isVisible()
				&& gearText
						.containsText("You need your head, right hand and two free")) {
			if (Inventory.getCount() < 28) {
				status = "Removing head gear";
				removeHeadGear();
				sleep(1100, 1300);
				status = "Banking";
				depositAllExcept(greenAttractor, greenBarrierGenerator,
						greenRepeller, yellowAttractor, yellowBarrierGenerator,
						yellowRepeller);
				sleep(1100, 1300);
			} else if (Inventory.getCount() == 28) {
				status = "Banking";
				depositAllExcept(greenAttractor, greenBarrierGenerator,
						greenRepeller, yellowAttractor, yellowBarrierGenerator,
						yellowRepeller);
				sleep(1100, 1300);
				status = "Removing head gear";
				removeHeadGear();
				sleep(1100, 1300);
				status = "Banking";
				depositAllExcept(greenAttractor, greenBarrierGenerator,
						greenRepeller, yellowAttractor, yellowBarrierGenerator,
						yellowRepeller);
				sleep(1100, 1300);
			}
			return;
		}
		if (infoText.isVisible()
				&& infoText.containsText("Waiting for orbs to appear")) {
			status = "Entering portal";
			if (portal == null) {
				return;
			}
			if (!portal.isOnScreen()) {
				Camera.turnTo(portal);
				sleep(1100, 1300);
			}
			if (!portal.isOnScreen()) {
				portal.getLocation().randomize(5, 5).clickOnMap();
				sleep(1100, 1300);
			}
			interact(portal, "Enter Portal");
			sleep(1100, 1300);
			return;
		}
		if (infoText.isVisible()
				&& (infoText.containsText("Waiting for players to join") || infoText
						.containsText("Waiting for portal to open"))) {
			status = "Waiting for portal to open";
			if (Widgets.canContinue()) {
				Widgets.clickContinue();
			}
			Tile loc = new Tile(1696, 5473);
			if (!Calculations.isTileOnScreen(loc)) {
				loc.randomize(3, 3).clickOnMap();
				sleep(1100, 1300);
			}
			if (defend) {
				Item repeller = Inventory
						.getItem(greenRepeller, yellowRepeller);
				if (Inventory.containsOneOf(greenRepeller, yellowRepeller)
						&& repeller != null) {
					repeller.click(true);
					sleep(1100, 1300);
				}
			} else {
				Item attractor = Inventory.getItem(greenAttractor,
						yellowAttractor);
				if (Inventory.containsOneOf(greenAttractor, yellowAttractor)
						&& attractor != null) {
					attractor.click(true);
					sleep(1100, 1300);
				}
			}
			if (infoText.containsText("Waiting for portal to open")) {
				final GameObject hover = Objects.getNearest(38376);
				if ((hover == null || !hover.isOnScreen())
						&& (portal == null || !portal.isOnScreen())) {
					return;
				}
				if (!objectContainsMouse(hover) && !npcContainsMouse(portal)) {
					if (hover == null || !hover.isOnScreen()) {
						Mouse.move(getRandomPoint(portal.getModel()));
					} else {
						Mouse.move(getRandomPoint(hover.getModel()));
					}
				}
			}
			sleep(500, 900);
			return;
		}
		if (waitText.isVisible() && waitText.containsText("new game for ")) {
			status = "Waiting for new game";
			final String text = waitText.getText();
			final int minutes = Integer.valueOf(text.replace("new game for ",
					"").replace(" minutes.", ""));
			waitFor(Random.nextInt((minutes * 60000) - 30000,
					(minutes * 60000) + 30000));
			return;
		}
		if (waitText.isVisible()
				&& waitText.containsText("Try again in a few minutes")) {
			status = "Waiting for next game";
			waitFor(Random.nextInt(0, 60000));
			return;
		}
		if (Widgets.canContinue()) {
			Widgets.clickContinue();
			sleep(300, 500);
			return;
		}
		return;
	}

	@Override
	public String getStatus() {
		return status;
	}

	private boolean removeHeadGear() {
		if (Equipment.getWidget().getComponent(Equipment.HELMET).getModelId() != -1
				|| Equipment.getItem(Equipment.HELMET) != null) {
			Equipment.getWidget().getComponent(Equipment.HELMET)
					.interact("Remove");
			sleep(1100, 1300);
		}
		return Equipment.getWidget().getComponent(Equipment.HELMET)
				.getModelId() == -1
				|| Equipment.getItem(Equipment.HELMET) == null;
	}

	private boolean depositAllExcept(final int... ids) {
		final GameObject depoBox = Objects.getNearest(24995);
		if (!Bank.DepositBox.isOpen()) {
			if (depoBox != null) {
				if (!depoBox.isOnScreen()) {
					Camera.turnTo(depoBox);
					sleep(1100, 1300);
				}
				interact(depoBox, "Deposit Deposit Box");
				sleep(1100, 1300);
			}
		}
		if (Inventory.containsOneOf(ids)) {
			for (final Item item : Inventory.getItems()) {
				if (item == null) {
					continue;
				}
				for (int id : ids) {
					if (item.getId() == id) {
						continue;
					}
				}
				item.interact("Deposit-All " + item.getName());
				sleep(1100, 1300);
			}
			return !Inventory.containsOneOf(ids);
		} else {
			final Component depoAll = Widgets.getComponent(11, 18);
			if (depoAll.isValid() && depoAll.isVisible()) {
				depoAll.click();
				sleep(1100, 1300);
			}
			return Inventory.getCount() == 0;
		}
	}

	private boolean npcContainsMouse(final Npc npc) {
		if (npc == null || npc.getModel() == null) {
			return false;
		}
		for (Polygon poly : npc.getModel().getTriangles()) {
			if (poly.contains(Mouse.getLocation())) {
				return true;
			}
		}
		return false;
	}

	private boolean objectContainsMouse(final GameObject go) {
		if (go == null || go.getModel() == null) {
			return false;
		}
		for (Polygon poly : go.getModel().getTriangles()) {
			if (poly.contains(Mouse.getLocation())) {
				return true;
			}
		}
		return false;
	}

	private void waitFor(final int time) {
		final long endTime = System.currentTimeMillis() + time;
		if (Widgets.canContinue()) {
			Widgets.clickContinue();
			sleep(1100, 1300);
		}
		while (System.currentTimeMillis() < endTime) {
			if (!Mouse.isPresent()) {
				sleep(10, 25);
			}
			Mouse.moveOffScreen();
		}
	}
}